package avl.non_recursion_2;

/**
 * 节点类
 *
 * @param <V> 元素
 * @author xing
 * @date 2023-01-10 13:46:57
 */
public class Node<V extends Comparable<V>> {
    private Node<V> parent;
    private Node<V> left;
    private Node<V> right;
    private int height;
    private V element;


//    /**
//     *
//     */
//    public void setParentNullAndUpdateParent() {
//
//    }

    /**
     * 不知道节点大小，经过判断，将节点作为到 root 的左节点或右节点，且将自己的设为父节点<br>
     *
     * @param node 要作为左节点或右节点的节点
     */
    public void setLeftOrRightAndAsParent(Node<V> node) {
        // 构造函数只给了 传入 element 的，所以这里 element 不可能为空，
        // node.element ，嗯，为 null 就报错呗，没法判断，正常情况下，节点为 null 应该在外边做判断并处理
        if (node == null) {
            throw new IllegalArgumentException("节点为 null，无法判断作为左节点或右节点");
        }
        if (element.compareTo(node.element) < 0) {
            this.setRightAndAsParent(node);
        } else if (element.compareTo(node.element) > 0) {
            this.setLeftAndAsParent(node);
        } else {
            // 这里也可以不抛出异常，直接啥都不写
            throw new IllegalArgumentException("元素值相同，插入失败");
        }
    }

//    /**
//     * 不知道节点大小，经过判断，将节点作为到 root 的左节点或右节点，<br>
//     *
//     * @param node 要作为左节点或右节点的节点
//     */
//    public void setLeftOrRight(Node<V> node) {
//        // 构造函数只给了 传入 element 的，所以这里 element 不可能为空，
//        // node.element ，嗯，为 null 就报错呗，没法判断，正常情况下，节点为 null 应该在外边做判断并处理
//        if (node == null) {
//            throw new IllegalArgumentException("节点为 null，无法判断作为左节点或右节点");
//        }
//        if (element.compareTo(node.element) < 0) {
//            this.setRight(node);
//        } else {
//            this.setLeft(node);
//        }
//    }

    /**
     * 设置左节点，同时将自己修改为父节点
     */
    public void setLeftAndAsParent(Node<V> left) {
        this.left = left;
        // reComputerHeight();
        if (left != null) {
            left.setParent(this);
        }
    }

    /**
     * 设置右节点，同时将自己修改为父节点
     */
    public void setRightAndAsParent(Node<V> right) {
        this.right = right;
        // reComputerHeight();
        if (right != null) {
            right.setParent(this);
        }
    }


    /**
     * 计算高度
     */
    public void reComputerHeight() {
        int lHeight = left == null ? 0 : left.height;
        int rHeight = right == null ? 0 : right.height;
        this.height = Math.max(rHeight, lHeight) + 1;
    }

    /**
     * 向父节点链式计算修改高度 <br>
     * 因为非递归方式，很多地方执行完不会像递归那样往父节点走了，就需要链式自底向上修改高度
     */
    public void chainedReComputerHeight() {
        reComputerHeight();
        if (parent != null) {
            parent.chainedReComputerHeight();
        }
    }

    public Node(V element) {
        this.height = 1;
        this.element = element;
    }

    public Node<V> getParent() {
        return parent;
    }

    public void setParent(Node<V> parent) {
        this.parent = parent;
    }

    public Node<V> getLeft() {
        return left;
    }

    public void setLeft(Node<V> left) {
        this.left = left;
        // reComputerHeight();
    }

    public Node<V> getRight() {
        return right;
    }

    public void setRight(Node<V> right) {
        this.right = right;
        // reComputerHeight();
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public V getElement() {
        return element;
    }

    public void setElement(V element) {
        this.element = element;
    }
}
